﻿using Base.FileRemoteModel.UpFile.Model;
using Base.FileRemoteModel.UserFile.Model;
using Base.HrExtendService;
using Basic.HrCollect;
using Basic.HrModel.SignatureFile;
using Basic.HrRemoteModel;
using Basic.HrRemoteModel.EmpSignatureFile.Model;
using Basic.HrService.Helper;
using Basic.HrService.Helper.Model;
using Basic.HrService.Interface;
using WeDonekRpc.Helper;

namespace Basic.HrService.Extend
{
    internal class EmpSignFileCreateService : IEmpSignFileCreateService
    {
        private readonly IEmpSignatureFileCollect _Service;
        private readonly IHrEmpSignConfig _Config;
        private readonly IFileService _File;
        public EmpSignFileCreateService ( IEmpSignatureFileCollect service, IHrEmpSignConfig config, IFileService file )
        {
            this._File = file;
            this._Config = config;
            this._Service = service;
        }
        public long AddUpCert ( UpSignFileAdd add )
        {
            UserFileStream file = this._File.GetStream(add.FileId);
            CertInfo cert = PfxCertFileHelper.GetCertificateFromPfxFile(new MemoryStream(file.Stream), add.CertPwd);
            if ( cert == null )
            {
                throw new ErrorException("hr.emp.cert.pwd.error");
            }
            long id = this._Service.Add(new SignatureFileAdd
            {
                SignName = cert.To.GetValueOrDefault("CN", string.Empty),
                CertPwd = this._Config.Encryption(add.CertPwd),
                Email = cert.To.GetValueOrDefault("E", string.Empty),
                EmpId = add.EmpId,
                EncryptionType = HrCertEncryptionType.未知,
                IsEmpUp = true,
                Company = cert.To.GetValueOrDefault("O", string.Empty),
                Country = cert.To.GetValueOrDefault("C", string.Empty),
                Dept = cert.To.GetValueOrDefault("OU", string.Empty),
                FileId = add.FileId,
                FileUri = file.FileUri.AbsoluteUri,
                BeginTime = cert.BeginTime,
                EndTime = cert.EndTime,
            });
            this._File.Save(add.FileId, id);
            return id;
        }
        public long Add ( SelfSignFileAdd add )
        {
            byte[] cert = this._CreateCertificate(add);
            FileSaveResult result = this._File.UpFile(new FileSaveDatum
            {
                DirKey = this._Config.CertUpDir,
                FileName = add.SignName + ".pfx",
                UserId = add.EmpId,
                UserType = "emp"
            }, cert);
            long id = this._Service.Add(new SignatureFileAdd
            {
                SignName = add.SignName,
                CertPwd = this._Config.Encryption(add.CertPwd),
                Email = add.Email,
                EmpId = add.EmpId,
                EncryptionType = add.EncryptionType,
                IsEmpUp = false,
                Company = add.Company,
                Country = add.Country,
                Dept = add.Dept,
                FileId = result.FileId.Value,
                FileUri = result.FileUri,
                BeginTime = add.BeginTime,
                EndTime = add.EndTime,
            });
            this._File.Save(result.FileId.Value, id);
            return id;
        }
        private byte[] _CreateCertificate ( SelfSignFileAdd data )
        {
            CertEmp to = new CertEmp
            {
                Dept = data.Dept,
                Company = data.Company,
                Country = data.Country ?? "CN",
                Email = data.Email,
                SignName = data.SignName,
            };
            CertBody cert = new CertBody
            {
                BeginTime = data.BeginTime,
                EndTime = data.EndTime,
                CertName = this._Config.CertName,
                Pwd = data.CertPwd,
                Source = this._Config.Source == null ? to : new CertEmp
                {
                    Dept = this._Config.Source.Dept,
                    Company = this._Config.Source.Company,
                    Country = this._Config.Source.Country ?? "CN",
                    Email = this._Config.Source.Email,
                    SignName = this._Config.Source.SignName,
                },
                To = to
            };
            if ( data.EncryptionType == HrRemoteModel.HrCertEncryptionType.SM2 )
            {
                return PfxCertFileHelper.CreateSM2Cert(cert);
            }
            else
            {
                int size = data.EncryptionType == HrRemoteModel.HrCertEncryptionType.RSA2048 ? 2048 : 3072;
                return PfxCertFileHelper.CreateRSACert(cert, size);
            }
        }
    }
}
